/**
 * 状态模式
 */
//  当一个对象的内在状态改变时允许改变其行为，这个对象看起来像是改变了其类。
// 通俗地说，状态模式就是一个关于多态的设计模式
// 如果一个对象有多种状态，并且每种状态下的行为不同，一般的做法是在这个对象的各个行为中添加 if-else 或者 switch-case 语句。
// 但更好的做法是为每种状态创建一个状态对象，使用状态对象替换掉这些条件判断语句，使得状态控制更加灵活，扩展性也更好

// NORMAL 代表普通用户状态，PLUS 代表 PLUS 会员状态
enum State {
    NORMAL,
    PLUS,
}

// 用户的功能接口：
interface IUser {
    // 开始模拟面试
    mockInterview(): void;
}

// 用户状态切换接口
interface ISwitchState {
    purchasePlus(): void;

    expire(): void;
}

class Normal implements IUser {
    mockInterview() {
        console.log('模拟面试是 Plus 会员专享功能');
    }
}
class Plus implements IUser {
    mockInterview() {
        console.log('开始模拟面试');
    }
}

class User implements IUser, ISwitchState {
    // private state = State.NORMAL;
    private state = new Normal();

    mockInterview() {
        // 在《代码整洁之道》、《重构》两本书中都提到：应使用多态取代条件表达式
        // if (this.state == State.PLUS) {
        //     console.log('开始模拟面试');
        // } else {
        //     console.log('模拟面试是 Plus 会员专享功能');
        // }
        this.state.mockInterview();
    }
    // 充值
    purchasePlus() {
        this.state = new Plus();
    }
    // 到期
    expire() {
        this.state = new Normal();
    }
}
// 用户初始状态为普通用户
const user = new User();
// 输出：模拟面试是 Plus 会员专享功能
user.mockInterview();

// 用户购买 Plus 会员，状态改变
user.purchasePlus();
// 输出：开始模拟面试
user.mockInterview();

// Plus 会员过期，变成普通用户，状态改变
user.expire();
// 输出：模拟面试是 Plus 会员专享功能
user.mockInterview();

// 可以看到，用户状态改变后，行为也随着改变了，这就是状态模式定义的由来，
// 它的优点是：将与特定状态相关的行为封装到一个状态对象中，
// 使用多态代替 if-else 或者 switch-case 状态判断。缺点是必然导致类增加，这也是使用多态不可避免的缺点。
